#!/usr/bin/env python
# encoding: utf-8


"""
@file: hanjueduizhi.py
@time: 2017/5/11 下午4:16
"""
from mathsolver.functions.base import *
from mathsolver.functions.budengshi import common_opers as co
from operator import itemgetter


# 目标函数含有绝对值的线性规划
# style1 Input paramer1: 不等式组; paramer2: 目标表达式; paramer3: 最值文本
class HanJueDuiZhiXianXingGuiHua(BaseFunction):
    def solver(self, *args):
        self.label.add('目标函数含有绝对值的线性规划')
        arg1, arg2, arg3 = args
        arg2 = list(co.flatten([arg2.sympify()]))
        assign_z = None
        if len(arg2) == 1:
            target_f = arg2[0]
        elif len(arg2) == 2:
            assign_z, target_f = arg2
        else:
            raise Exception('Illegal parameter')
        text = arg3
        abs_exprs = co.find_abs_items(target_f)
        if not abs_exprs:
            raise Exception('Type Match Error')
        abs_expr = abs_exprs[0]
        ineqs = co.simp_ineqs(arg1).sympify()  # 规范化不等式组
        ineq_fs = map(lambda _: _[0] - _[2], ineqs)  # 每个不等式对应的直线
        intersects = co.satisfied_ineqs_intersections(ineqs)  # 交点
        intersetc_points = map(itemgetter(1), intersects)
        self.steps.append(['如图所示不等式组:' + BaseIneqs(ineqs).printing(), '边界的交点为:'])
        points = map(lambda _: (_[0][1], _[1][1]), intersetc_points)
        points_print = ''
        for index, point in enumerate(points):
            if index == 0:
                points_print += '(' + new_latex(point[0]) + ',' + new_latex(point[1]) + ')'
            else:
                points_print += '或(' + new_latex(point[0]) + ',' + new_latex(point[1]) + ')'
        self.steps.append([points_print, ''])
        target_f_inters_points = map(lambda _: co.two_line_intersections([abs_expr, '0'], [_, '0']),
                                     ineq_fs)  # 求直线与不等式组中所有直线的交点
        target_f_inters_points = filter(lambda _: co.satisfied_ineqs(ineqs, _), target_f_inters_points)  # 过滤掉不满足不等式组的交点
        points = map(lambda _: (_[0][1], _[1][1]), target_f_inters_points)
        self.steps.append(['直线' + BaseEq([abs_expr, '0']).printing(), '与不等式区域的交点为:'])
        points_print = ''
        for index, point in enumerate(points):
            if index == 0:
                points_print += '(' + new_latex(point[0]) + ',' + new_latex(point[1]) + ')'
            else:
                points_print += '或(' + new_latex(point[0]) + ',' + new_latex(point[1]) + ')'
        self.steps.append([points_print, ''])
        all_points = list(co.ichain(intersetc_points, target_f_inters_points))
        target_f_vs = map(target_f.subs, all_points)
        max_value = max(target_f_vs)
        min_value = min(target_f_vs)
        self.steps.append(['将交点依次带入目标表达式得:', ''])
        if text.find('最大值') >= 0:
            self.output.append(BaseNumber(max_value))
            self.steps.append(['求得最大值为:', new_latex(max_value)])
        elif text.find('最小值') >= 0:
            self.output.append(BaseNumber(min_value))
            self.steps.append(['求得最小值为:', new_latex(max_value)])
        else:
            f_interval = Interval(min_value, max_value)
            self.steps.append(['取值范围为:', new_latex(f_interval)])
            if assign_z:
                self.output.append(BaseSymbolValue({assign_z: f_interval}))
            else:  # 没有指定z
                self.output.append(co.to_base_interval(f_interval))
        return self


if __name__ == '__main__':
    _solve = HanJueDuiZhiXianXingGuiHua().solver(
        BaseIneqs([['x - y + 3', '>=', '0'], ['x + y - 6', '<=', '0'], ['y', '>=', '0']]),
        BaseEq(['z', 'y - 3*Abs(x)']), '最大值')
